/*******************************************************************************
* file  : multi alloc
* creat : apleilx
* data  : 2021/09/26
*******************************************************************************/
#ifndef _MULTI_MALLOC_H
#define _MULTI_MALLOC_H

#include "stdlib.h"
#include "mytype.h"

#ifdef	__cplusplus
extern "C" {
#endif

#define MULTI_MEM_ERR_NONE			0
#define MULTI_MEM_ERR_BLOCKS		1
#define MULTI_MEM_ERR_MEM_BASE		2
#define MULTI_MEM_ERR_BLOCK_SIZE	3
	
	/***************************************************************************
	* @brief  对象运行信息
	***************************************************************************/
	typedef struct
	{
		uu8 init_ok;
		uu8 err;
		uu32 used_now;
		uu32 used_max;
	} multi_malloc_info_type;

	/***************************************************************************
	* @brief  对象API列表
	***************************************************************************/
	typedef struct
	{
		void * (*malloc)(size_t size);
		void * (*calloc)(size_t num, size_t size);
		void * (*realloc)(void *, size_t size);
		void(*free)(void *);
		uu16(*perused)(void);
	} multi_malloc_api_type;

	/***************************************************************************
	* @brief  对象数据结构
	***************************************************************************/
	typedef struct
	{
		uu64 *mem;							// 内存基址
		uu16 *mem_tab;						// 分配表
		uu32 mem_size;						// 内存尺寸
		uu16 block_size;					// 块大小-分配单位
		uu32 block_amount;					// 块数量
		uu16(*lock)(void);					// 互斥锁请求
		void(*unlock)(void);				// 互斥锁释放
		multi_malloc_info_type *info;		// 运行信息-必要
		const multi_malloc_api_type *api;	// 对象接口-可选
	} multi_malloc_type;

	/***************************************************************************
	* @brief  接口 - 单次最大可申请内存数为 block_size*64k - 1
	***************************************************************************/
	void multi_malloc_init(const multi_malloc_type*obj);
	void * multi_malloc(const multi_malloc_type*obj, size_t size);
	void * multi_calloc(const multi_malloc_type*obj, size_t num, size_t size);
	void * multi_realloc(const multi_malloc_type*obj, void *, size_t size);
	void multi_free(const multi_malloc_type*obj, void *);
	uu16 multi_malloc_perused(const multi_malloc_type *obj);

	/***************************************************************************
	* @brief  对象接口
	***************************************************************************/
	#define multi_malloc_api_name(obj)	&obj##_api
	#define multi_malloc_api_ref(obj)	const multi_malloc_api_type  obj##_api
	#define multi_malloc_api_link(obj)	obj.api=obj##_api	// 非const结构使用
	
	#define multi_malloc_api_make(obj)										\
	void * obj##_malloc(size_t size){return multi_malloc(&obj, size);}		\
	void * obj##_calloc(size_t num, size_t size)							\
			{return multi_calloc(&obj, num, size);}							\
	void * obj##_realloc(void *p, size_t size)								\
			{return multi_realloc(&obj, p, size);}							\
	void obj##_free(void *p){ multi_free(&obj, p);}							\
	uu16 obj##_perused(void){ return multi_malloc_perused(&obj);}			\
	const multi_malloc_api_type  obj##_api = {								\
		obj##_malloc,														\
		obj##_calloc,														\
		obj##_realloc,														\
		obj##_free,															\
		obj##_perused														\
	}
	
	/***************************************************************************
	* @brief  END
	***************************************************************************/
#ifdef	__cplusplus
}
#endif

#endif

